package com.inifitness.tenant.core.config.mp.service.impl;

import java.nio.charset.StandardCharsets;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.inifitness.common.exceptions.BizException;
import com.inifitness.common.result.ResultCode;
import com.inifitness.tenant.core.config.mp.service.EncryptService;

import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * AES加解密组件 用于存储需要加密的字段
 *
 * @author sunjinfeng
 * @version 1.0.0
 * @since 2024-01-09 16:38
 */
@Log4j2
@Component
@ConditionalOnProperty(value = "mp.encrypt.type", havingValue = "aes")
@ConfigurationProperties(prefix = "mp.encrypt")
@RequiredArgsConstructor
@Data
public class AESEncryptService implements EncryptService {

  private String key;
  private String iv;

  @Override
  public String encrypt(String content) {
    try {
      SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8),
          Constants.AES);
      byte[] enCodeFormat = secretKey.getEncoded();
      SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, Constants.AES);
      IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
      Cipher cipher = Cipher.getInstance(Constants.AES_CBC_CIPHER);
      cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
      byte[] valueByte = cipher.doFinal(content.getBytes(StandardCharsets.UTF_8));
      return Base64.getEncoder().encodeToString(valueByte);
    } catch (InvalidAlgorithmParameterException | NoSuchPaddingException |
             IllegalBlockSizeException | NoSuchAlgorithmException | BadPaddingException |
             InvalidKeyException e) {
      log.error("加密失败: {}", e.getMessage(),e);
      throw new BizException(ResultCode.USER_ERROR,e);
    }
  }

  @Override
  public String decrypt(String content) {
    try {
      byte[] originalData = Base64.getDecoder().decode(content.getBytes(StandardCharsets.UTF_8));
      SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8),
          Constants.AES);
      byte[] enCodeFormat = secretKey.getEncoded();
      SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, Constants.AES);
      IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes(StandardCharsets.UTF_8));
      Cipher cipher = Cipher.getInstance(Constants.AES_CBC_CIPHER);
      cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);
      byte[] valueByte = cipher.doFinal(originalData);
      return new String(valueByte);
    } catch (InvalidAlgorithmParameterException | NoSuchPaddingException |
             IllegalBlockSizeException | NoSuchAlgorithmException | BadPaddingException |
             InvalidKeyException e) {
      log.error("加密失败: {}", e.getMessage(),e);
      throw new BizException(ResultCode.USER_ERROR,e);
    }
  }
}
